home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 4 / Meeting Pearls Vol. IV (1996)(GTI - Schatztruhe)[!].iso / Pearls / dev / Debug / Flush / Flush.c < prev    next >
C/C++ Source or Header  |  1995-11-11  |  10KB  |  400 lines

  1. /*
  2.  * Flush
  3.  * Selectively remove unused libraries, devices and fonts from memory.
  4.  *
  5.  * Written by Septh (Stephan Schreiber)
  6.  * FreeWare - Use at will!
  7.  */
  8.  
  9. #include <string.h>
  10. #include <exec/types.h>
  11. #include <exec/nodes.h>
  12. #include <exec/lists.h>
  13. #include <exec/memory.h>
  14. #include <exec/libraries.h>
  15. #include <exec/devices.h>
  16. #include <exec/execbase.h>
  17. #include <dos/dos.h>
  18. #include <dos/dosasl.h>
  19. #include <graphics/text.h>
  20. #include <graphics/gfxbase.h>
  21.  
  22. #include <clib/exec_protos.h>
  23. #include <clib/dos_protos.h>
  24. #include <clib/graphics_protos.h>
  25.  
  26. #include <pragmas/exec_sysbase_pragmas.h>
  27. #include <pragmas/dos_pragmas.h>
  28. #include <pragmas/graphics_pragmas.h>
  29.  
  30. /******************************************************************************
  31.  * Constants and macros
  32.  ******************************************************************************/
  33. #define    TEMPLATE    "NAMES/M,LIBS=LIBRARIES/S,DEVS=DEVICES/S,FONTS/S,ALL/S,QUIET/S"
  34. enum
  35. {    OPT_NAMES = 0,    // Name(s) of libs/devs/fonts to flush
  36.     OPT_LIBS,        // Limit flush to libraries
  37.     OPT_DEVS,        // Limit flush to devices
  38.     OPT_FONTS,        // Limit flush to fonts
  39.     OPT_ALL,        // Flush libs, devs AND fonts
  40.     OPT_QUIET,        // Shut up!
  41.     NUM_OPTS
  42. };
  43.  
  44. /* Short-cuts */
  45. #define    lib_Succ    lib_Node.ln_Succ
  46. #define    lib_Name    lib_Node.ln_Name
  47.  
  48. #define    dd_Succ        dd_Library.lib_Node.ln_Succ
  49. #define    dd_Name        dd_Library.lib_Node.ln_Name
  50.  
  51. #define    tf_Succ        tf_Message.mn_Node.ln_Succ
  52. #define    tf_Name        tf_Message.mn_Node.ln_Name
  53.  
  54. /******************************************************************************
  55.  * Globals
  56.  ******************************************************************************/
  57. UBYTE *version = "\0$VER: Flush 1.1b (12.11.95)";
  58.  
  59. struct Library *SysBase;
  60. struct Library *DOSBase;
  61. struct Library *GfxBase;
  62.  
  63. UBYTE *def_names[] =
  64. {    "#?",
  65.     NULL
  66. };
  67.  
  68. /******************************************************************************
  69.  * Prototypes
  70.  ******************************************************************************/
  71. LONG flush_fonts(UBYTE **names, LONG quiet);
  72. LONG flush_devs(UBYTE **names, LONG quiet);
  73. LONG flush_libs(UBYTE **names, LONG quiet);
  74.  
  75. /******************************************************************************
  76.  * Program entry point
  77.  ******************************************************************************/
  78. LONG __saveds main(UBYTE *cmdline)
  79. {
  80. struct Process *me;
  81. struct Message *wbmsg;
  82. struct RDArgs *rda;
  83. ULONG opts[NUM_OPTS];
  84. LONG num_flushed, num;
  85. BOOL again;
  86.  
  87.     /* Get SysBase */
  88.     SysBase = *((struct Library **)4L);
  89.  
  90.     /* Minimal WB startup */
  91.     me = (struct Process *)FindTask(NULL);
  92.     if (me->pr_CLI == NULL)
  93.     {    WaitPort(&me->pr_MsgPort);
  94.         wbmsg = GetMsg(&me->pr_MsgPort);
  95.     }
  96.     else wbmsg = NULL;
  97.  
  98.     /* Open the libraries */
  99.     if (DOSBase= OpenLibrary("dos.library", 37L))
  100.     {    if (GfxBase = OpenLibrary("graphics.library", 0L))
  101.         {    /* When run under Workbench,
  102.              * no arguments are usable.
  103.              */
  104.             if (wbmsg)
  105.             {    flush_fonts(def_names, TRUE);
  106.                 flush_devs(def_names, TRUE);
  107.                 flush_libs(def_names, TRUE);
  108.             }
  109.             else
  110.             {    /* Get shell arguments */
  111.                 memset(opts, '\0', sizeof(opts));
  112.                 rda = ReadArgs(TEMPLATE, opts, NULL);
  113.  
  114.                 /* Break ? */
  115.                 if (CheckSignal(SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
  116.                 {    if (rda)
  117.                     {    FreeArgs(rda);
  118.                         rda = NULL;
  119.                     }
  120.                     SetIoErr(ERROR_BREAK);
  121.                 }
  122.  
  123.                 if (rda)
  124.                 {    /* ALL ? */
  125.                     if (opts[OPT_ALL] || (!opts[OPT_LIBS] && !opts[OPT_DEVS] && !opts[OPT_FONTS]))
  126.                     {    opts[OPT_LIBS]  = /*DOSTRUE;*/
  127.                         opts[OPT_DEVS]  = /*DOSTRUE;*/
  128.                         opts[OPT_FONTS] = DOSTRUE;
  129.                     }
  130.  
  131.                     /* New to version 1.1:
  132.                      * since libraries or devices may open other libraries, devices or fonts,
  133.                      * and close them only when they are flushed (possibly leaving them
  134.                      * with an open count of 0), we have to loop until everything really gets flushed.
  135.                      */
  136.                     num_flushed = 0;
  137.  
  138.                     do
  139.                     {    again = FALSE;
  140.  
  141.                         /* Here we begin with fonts for aesthetics reasons:
  142.                          * if we flushed the libraries before the fonts,
  143.                          * then we could not report which fonts would get flushed.
  144.                          * This is because when flushed, diskfont.library
  145.                          * simply removes all unsued fonts still in memory.
  146.                          */
  147.                         /* FONTS ? */
  148.                         if (opts[OPT_FONTS])
  149.                         {    if (num = flush_fonts((UBYTE **)opts[OPT_NAMES], opts[OPT_QUIET]))
  150.                             {    num_flushed += num;
  151.                                 again = TRUE;
  152.                             }
  153.                         }
  154.  
  155.                         /* These two could use a single function... */
  156.                         /* DEVS ? */
  157.                         if (opts[OPT_DEVS])
  158.                         {    if (num = flush_devs((UBYTE **)opts[OPT_NAMES], opts[OPT_QUIET]))
  159.                             {    num_flushed += num;
  160.                                 again = TRUE;
  161.                             }
  162.                         }
  163.  
  164.                         /* LIBS ? */
  165.                         if (opts[OPT_LIBS])
  166.                         {    if (num = flush_libs((UBYTE **)opts[OPT_NAMES], opts[OPT_QUIET]))
  167.                             {    num_flushed += num;
  168.                                 again = TRUE;
  169.                             }
  170.                         }
  171.  
  172.                         /* Loop until every flushable little thing is flushed */
  173.                     } while (again);
  174.  
  175.                     /* Report what we did */
  176.                     if (!opts[OPT_QUIET])
  177.                         Printf("%ld elements flushed\n", num_flushed);
  178.  
  179.                     FreeArgs(rda);
  180.                 }
  181.                 else PrintFault(IoErr(), NULL);
  182.             }
  183.             CloseLibrary(GfxBase);
  184.         }
  185.         CloseLibrary(DOSBase);
  186.     }
  187.  
  188.     /* Back to WB ? */
  189.     if (wbmsg)
  190.     {    Forbid();
  191.         ReplyMsg(wbmsg);
  192.     }
  193.  
  194.     return(RETURN_OK);
  195. }
  196.  
  197. /******************************************************************************
  198.  * Flush unused fonts
  199.  ******************************************************************************/
  200. LONG flush_fonts(UBYTE **names, LONG quiet)
  201. {
  202. struct List *fonts_list;
  203. struct TextFont *font;
  204. UBYTE pat[256], font_name[256];
  205. UWORD font_size;
  206. struct TextFont *tmp_font;
  207. LONG num = 0;
  208.  
  209.     /* Get the fonts list */
  210.     fonts_list = &(((struct GfxBase *)GfxBase)->TextFonts);
  211.  
  212.     if (names == NULL)
  213.         names = def_names;
  214.  
  215.     while (*names)
  216.     {    /* Allow for wildcards in names */
  217.         ParsePatternNoCase(*names++, pat, sizeof(pat));
  218.  
  219.         Forbid();
  220.  
  221.         /* For each font in the system... */
  222.         for (font = (struct TextFont *)fonts_list->lh_Head; font->tf_Succ; font = (struct TextFont *)font->tf_Succ)
  223.         {    /* Check number of accessors to this font
  224.              * See if name matches
  225.              */
  226.             if ((font->tf_Accessors == 0) && MatchPatternNoCase(pat, font->tf_Name))
  227.             {    /* Copy name in temp buffer */
  228.                 strcpy(font_name, font->tf_Name);
  229.  
  230.                 /* Copy font size, too */
  231.                 font_size = font->tf_YSize;
  232.  
  233.                 /* Ok, let's flush it */
  234.                 StripFont(font);    // Fonts won't flush without this!
  235.                 RemFont(font);
  236.  
  237.                 /* Check if it really flushed */
  238.                 tmp_font = (struct TextFont *)fonts_list;
  239.                 while (tmp_font = (struct TextFont *)FindName((struct List *)tmp_font, font_name))
  240.                 {    if (tmp_font == font)
  241.                         break;
  242.                 }
  243.  
  244.                 if (tmp_font == NULL)
  245.                 {    num++;
  246.  
  247.                     /* Tell them it's done */
  248.                     if (!quiet)
  249.                     {    Permit();
  250.                         Printf("font \"%s\", size %ld flushed\n", font_name, font_size);
  251.                         Forbid();
  252.                     }
  253.  
  254.                     /* Go back to start of list.
  255.                      * Note that because we are in a for() loop,
  256.                      * the 'font = font->tf_Succ' statement
  257.                      * will be executed *after* this one.
  258.                      * So we have to make 'font' point to
  259.                      * the list header rather than to the head node,
  260.                      * or we'll miss the first font in the list.
  261.                      */
  262.                     font = (struct TextFont *)fonts_list;
  263.                 }
  264.             }
  265.         }
  266.  
  267.         Permit();
  268.     }
  269.  
  270.     return(num);
  271. }
  272.  
  273. /******************************************************************************
  274.  * Flush unused devices
  275.  ******************************************************************************/
  276. LONG flush_devs(UBYTE **names, LONG quiet)
  277. {
  278. struct List *devs_list;
  279. struct Device *dev;
  280. UBYTE pat[256], dev_name[256];
  281. LONG num = 0;
  282.  
  283.     /* Get the devices list */
  284.     devs_list = &(((struct ExecBase *)SysBase)->DeviceList);
  285.  
  286.     if (names == NULL)
  287.         names = def_names;
  288.  
  289.     while (*names)
  290.     {    /* Allows for wildcards in names */
  291.         ParsePatternNoCase(*names++, pat, sizeof(pat));
  292.  
  293.         Forbid();
  294.  
  295.         /* for each device in the list... */
  296.         for (dev = (struct Device *)devs_list->lh_Head; dev->dd_Succ; dev = (struct Device *)dev->dd_Succ)
  297.         {    /* Check opencount of this device.
  298.              * See if name matches.
  299.              */
  300.             if ((dev->dd_Library.lib_OpenCnt == 0) && MatchPatternNoCase(pat, dev->dd_Name))
  301.             {    /* Copy name in temp buffer */
  302.                 strcpy(dev_name, dev->dd_Name);
  303.  
  304.                 /* Ok, let's flush it */
  305.                 RemDevice(dev);
  306.  
  307.                 /* Check if it really flushed */
  308.                 if (FindName(devs_list, dev_name) == NULL)
  309.                 {    num++;
  310.  
  311.                     /* Tell them it's done */
  312.                     if (!quiet)
  313.                     {    Permit();
  314.                         Printf("Device \"%s\" flushed\n", dev_name);
  315.                         Forbid();
  316.                     }
  317.  
  318.                     /* Go back to start of list.
  319.                      * Note that because we are in a for() loop,
  320.                      * the 'dev = dev->dd_Succ' statement
  321.                      * will be executed *after* this one.
  322.                      * So we have to make 'dev' point to
  323.                      * the list header rather than to the head node,
  324.                      * or we'll miss the first device in the list.
  325.                      */
  326.                     dev = (struct Device *)devs_list;
  327.                 }
  328.             }
  329.         }
  330.  
  331.         Permit();
  332.     }
  333.  
  334.     return(num);
  335. }
  336.  
  337. /******************************************************************************
  338.  * Flush unused libraries
  339.  ******************************************************************************/
  340. LONG flush_libs(UBYTE **names, LONG quiet)
  341. {
  342. struct List *libs_list;
  343. struct Library *lib;
  344. UBYTE pat[256], lib_name[256];
  345. LONG num = 0;
  346.  
  347.     /* Get the libraries list */
  348.     libs_list = &(((struct ExecBase *)SysBase)->LibList);
  349.  
  350.     if (names == NULL)
  351.         names = def_names;
  352.  
  353.     while (*names)
  354.     {    /* Allows for wildcards in names */
  355.         ParsePatternNoCase(*names++, pat, sizeof(pat));
  356.  
  357.         Forbid();
  358.  
  359.         /* for each library in the system... */
  360.         for (lib = (struct Library *)libs_list->lh_Head; lib->lib_Succ; lib = (struct Library *)lib->lib_Succ)
  361.         {    /* Check opencount of this library.
  362.              * See if name matches.
  363.              */
  364.             if ((lib->lib_OpenCnt == 0) && MatchPatternNoCase(pat, lib->lib_Name))
  365.             {    /* Copy name in temp buffer */
  366.                 strcpy(lib_name, lib->lib_Name);
  367.  
  368.                 /* Ok, let's flush it */
  369.                 RemLibrary(lib);
  370.  
  371.                 /* Check if it really flushed */
  372.                 if (FindName(libs_list, lib_name) == NULL)
  373.                 {    num++;
  374.  
  375.                     /* Tell them it's done */
  376.                     if (!quiet)
  377.                     {    Permit();
  378.                         Printf("Library \"%s\" flushed\n", lib_name);
  379.                         Forbid();
  380.                     }
  381.  
  382.                     /* Go back to start of list.
  383.                      * Note that because we are in a for() loop,
  384.                      * the 'lib = lib->lib_Succ' statement
  385.                      * will be executed *after* this one.
  386.                      * So we have to make 'lib' point to
  387.                      * the list header rather than to the head node,
  388.                      * or we'll miss the first library in the list.
  389.                      */
  390.                     lib = (struct Library *)libs_list;
  391.                 }
  392.             }
  393.         }
  394.  
  395.         Permit();
  396.     }
  397.  
  398.     return(num);
  399. }
  400.